/**
 * 
 */
package com.google.code.netz.wfe;

import java.util.UUID;

import com.google.code.netz.wfe.api.ILifecycleHandler;
import com.google.code.netz.wfe.api.IWorkflowContext;
import com.google.code.netz.wfe.api.IWorkflowEngine;
import com.google.code.netz.wfe.api.WorkflowException;
import com.google.code.netz.wfe.model.Activity;
import com.google.code.netz.wfe.model.ICase;
import com.google.code.netz.wfe.model.IResource;
import com.google.code.netz.wfe.model.State;
import com.google.code.netz.wfe.model.Transition;
import com.google.code.netz.wfe.model.WorkItem;

/**
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @since 1.0
 * @version $Id: DefaultWorkflowEngine.java 17 2009-02-09 13:08:49Z rahul.thakur.xdev $
 */
public class DefaultWorkflowEngine implements IWorkflowEngine {

	/**
	 * Name of this Resource.
	 */
	private static final String WFE_NAME = "Netz Workflow Engine";

	private ILifecycleHandler<ICase<?>> caseLifecycleHandler = new CaseLifecycleHandler();

	private ILifecycleHandler<Transition<?>> transitionLifecycleHandler = new TransitionLifecycleHandler();

	private ILifecycleHandler<WorkItem<?>> workItemLifecycleHandler = new WorkItemLifecycleHandler();

	private ILifecycleHandler<Activity> activityLifecycleHandler = new ActivityLifecycleHandler();

	/**
	 * Workflow Context specific to this Workflow engine.
	 * <p>
	 * TODO: Review if we need to create this separately.
	 */
	private IWorkflowContext context = new DefaultWorkflowContext(this);

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.model.IResource#getName()
	 */
	@Override
	public String getName() {
		return WFE_NAME;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#query(java.util.UUID,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public State query(UUID kaseId, IResource resource) throws WorkflowException {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#submit(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public <D> WorkItem<D> submit(ICase<D> kase, IResource resource) throws WorkflowException {
		// EventManager.getInstance().dispatchEvent(
		// new CaseEvent(kase, CaseEventType.CASE_SUBMITTED));
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			caseLifecycleHandler.start(kase, this.context);
			return accept(kase, resource);
		}
		return null;
	}

	/**
	 * 
	 * @param <D>
	 * @param kase
	 * @param resource
	 * @return
	 * @throws WorkflowException
	 */
	private <D> WorkItem accept(ICase<D> kase, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.start(kase, this.context);
			return new WorkItem<D>(kase, kase.getInitialTransition());
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#close(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public <D> void close(ICase<D> kase, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.stop(kase, this.context);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#open(com.google.code.netz.wfe.model.WorkItem,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public Activity open(WorkItem wi, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			workItemLifecycleHandler.start(wi, this.context);
			Activity activity = new Activity(wi, resource);
			activity.setActive(true);
			return activity;
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#resume(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public <D> void resume(ICase<D> kase, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.resume(kase, this.context);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#suspend(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public <D> void suspend(ICase<D> kase, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.suspend(kase, this.context);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#close(com.google.code.netz.wfe.model.Activity,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public void close(Activity activity, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			activityLifecycleHandler.stop(activity, this.context);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#fire(com.google.code.netz
	 *      .wfe.model.InternalTransition,
	 *      com.google.code.netz.wfe.model.IResource)
	 */
	@Override
	public void fire(Transition transition, IResource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			transitionLifecycleHandler.start(transition, this.context);
		}
	}

}
